package com.syf.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.alicloud.sms.ISmsService;
import com.alibaba.fastjson.JSON;
import com.aliyun.mns.common.ClientException;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.syf.domain.Config;
import com.syf.service.ConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.syf.domain.Sms;
import com.syf.mapper.SmsMapper;
import com.syf.service.SmsService;
/**
*
*
*@author 苏耀奋
*@create 2021-08-02 14:28
*/
@Service
@Slf4j
public class SmsServiceImpl extends ServiceImpl<SmsMapper, Sms> implements SmsService{

    @Autowired
    private ISmsService smsService; //alibaba架包中的 短信对象

    @Autowired
    private ConfigService configService; //全局参数配置

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 发送一个短信:
     *      前端传递的参数:
     *          templateCode      短信模板code(不如说是config中的 配置规则代码code)【根据此在config中查找 签名和真正的模板code】
     *          countryCode       国际区号
     *          mobile            手机号
     *
     * @param sms 短信内容
     * @return 是否发送成功
     */
    @Override
    public boolean sendSms(Sms sms) {
        log.info("发送短信{}", JSON.toJSONString(sms, true));
        //1.构建发送短信的请求对象
        SendSmsRequest request = buildSmsRequest(sms);
        try {
            //发送短信
            SendSmsResponse sendSmsResponse = smsService.sendSmsRequest(request);
            log.info("发送的结果为{}", JSON.toJSONString(sendSmsResponse, true));

            String code = sendSmsResponse.getCode();
            if ("OK".equals(code)) { // 发送成功,否则失败
                sms.setStatus(1);  //短信状态：0，默认值； 大于0，成功发送短信数量； 小于0，异常；
                return save(sms); //添加SMS短信表信息
            } else {
                return false;
            }
        } catch (ClientException | com.aliyuncs.exceptions.ClientException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 构建发送短信的请求对象:
     *      1.Config全局配置类中 由value值 存储SMS的 签名及模板code
     *        利用:配置规则代码code -> 查询:value值  -> 获取:SMS的签名及模板code
     *
     *      2.在全局变量config中，根据 配置规则代码code 查询 value值：
     *          1."SING" --> 签名(SYF商城)
     *          2.前端传递过来的规则代码"VERIFY_OLD_PHONE" --> SMS的模板code(SMS_222326304)
     *            新手机发送验证码规则"CHANGE_PHONE_VERIFY"
     *
     * @param sms
     * @return
     */
    private SendSmsRequest buildSmsRequest(Sms sms) {
        SendSmsRequest sendSmsRequest = new SendSmsRequest();
        //1.发送给哪个电话号码
        sendSmsRequest.setPhoneNumbers(sms.getMobile());

        //2.通过 规则的Code 查询签名(SYF商城):
        Config signConfig = configService.getConfigByCode("SING");
        sendSmsRequest.setSignName(signConfig.getValue()); // 设置签名---公司里面不会随便的改变--Config 查询签名

        //3.设置SMS的模板code: "WITHDRAW_MIN_AMOUNT" --> SMS的模板code(SMS_222326304)
        Config configByCode = configService.getConfigByCode(sms.getTemplateCode());
        if (configByCode == null) {
            throw new IllegalArgumentException("您输入的签名不存在");
        }
        sendSmsRequest.setTemplateCode(configByCode.getValue()); //模板的Code--动态改变
        //sms.setTemplateCode(configByCode.getValue());    这才是真正的 模板code

        //4.随机验证码【阿里云设置的模板: 您的动态码为${code},您正在进行手机号重置操作，如非本人操作，请忽略该信息。】
        String code = RandomUtil.randomNumbers(6);
        sendSmsRequest.setTemplateParam("{\"code\":\"" + code + "\"}");  //特殊规则（内容已经在阿里云上设置好了）

        //5.需要把code 保存到redis 里面,设置有效时间: 【key: SMS:VERIFY_OLD_PHONE:15827293117     value: 123456】
        redisTemplate.opsForValue().set("SMS:" + sms.getTemplateCode() + ":" + sms.getMobile(), code,5, TimeUnit.MINUTES);


        //模板内容： sign:您的验证码${code}，该验证码5分钟内有效，请勿泄漏于他人！
        String desc = configByCode.getDesc();
        String content = signConfig.getValue() + ":" + desc.replaceAll("\\$\\{code\\}", code);
        sms.setContent(content); // 短信的内容（用于存储在SMS表中，内容早已在阿里云上设置好了）

        return sendSmsRequest;
    }
}
